package handler

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/apache/rocketmq-client-go/v2"
	"github.com/apache/rocketmq-client-go/v2/consumer"
	"github.com/apache/rocketmq-client-go/v2/primitive"
	"github.com/apache/rocketmq-client-go/v2/producer"
	"go.uber.org/zap"
	"sale_system/order_srv/global"
	"sale_system/order_srv/model"
	"time"
)

// AutoTimeOut 读取延迟消息
func AutoTimeOut(ctx context.Context, msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {

	// 当我们订单在处理本地事务时，会发送一条延迟消息，用来后续我们判断是否出现超时未支付的现象
	for i := range msgs {
		var orderInfo model.OrderInfo
		_ = json.Unmarshal(msgs[i].Body, &orderInfo)

		zap.S().Info("获取到超时消息", time.Now())

		// 查询订单是否已经支付
		var order model.OrderInfo
		result := global.DB.Model(model.OrderInfo{}).Where(model.OrderInfo{OrderSn: orderInfo.OrderSn}).First(&order)
		//	没找到订单，丢弃消息
		if result.RowsAffected == 0 {
			return consumer.ConsumeSuccess, nil
		}
		// 没有支付成功，需要进行库存归还
		if order.Status != "TRADE_SUCCESS" {

			tx := global.DB.Begin()
			// 修改订单状态为超时支付
			order.Status = "TRADE_CLOSED"
			result = tx.Save(&order)
			if result.RowsAffected == 0 {
				tx.Rollback()
				zap.S().Info("保存订单消息失败, ", result.Error)
				return consumer.ConsumeRetryLater, nil
			}
			// 1.方案一我们可以调用库存子服务进行库存归还
			// 2.我们之间发送一条消息到InventoryReBack这个Topic下进行回滚，也就是订单创建那样，发送一个库存回滚消息

			address := fmt.Sprintf("%s:%d", global.ServerConfig.RocketMqInfo.Host, global.ServerConfig.RocketMqInfo.Port)

			Producer, err := rocketmq.NewProducer(producer.WithNameServer([]string{address}))
			if err != nil {
				tx.Rollback()
				zap.S().Info("获取生产者对象失败, ", err.Error())
				return consumer.ConsumeRetryLater, nil
			}

			if err = Producer.Start(); err != nil {
				tx.Rollback()
				zap.S().Info("启动生产者对象失败，%s ", err.Error())
				return consumer.ConsumeRetryLater, nil
			}

			// 将订单的信息维护起来，发给库存子服务
			msg := primitive.NewMessage("InventoryReBack", msgs[i].Body)
			_, err = Producer.SendSync(context.Background(), msg)
			if err != nil {
				tx.Rollback()
				zap.S().Info("发送库存扣减消息失败，%s", err.Error())
				return consumer.ConsumeRetryLater, nil
			}

			tx.Commit()
			// 库存归还后记得进行消息确认
			return consumer.ConsumeSuccess, nil
		}
	}
	return consumer.ConsumeSuccess, nil
}
